home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
cool
/
cool.lha
/
ice
/
CCC
/
CCC.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-04
|
55KB
|
1,953 lines
/*
Copyright (C) 1990 Texas Instruments Incorporated.
Permission is granted to any individual or institution to use, copy, modify,
and distribute this software, provided that this complete copyright and
permission notice is maintained, intact, in all copies and supporting
documentation.
Texas Instruments Incorporated provides this software "as is" without
express or implied warranty.
*
* C++ compiler driver
*
CCC (capital CCC) translates C++ source code to C source code.
The command uses cpp(1) for preprocessing, cfront for syntax
and type checking, and cc(1) for code generation.
CCC assumes arguments ending in
.c are C++ source programs; they are compiled, and each
object program is left on the file whose name is that
of the source with .o substituted for .c.
.s are assembly source programs; they are assembled into
.o files.
CCC interprets the following options:
-n Print what would have been done, but don't do it.
-v Verbose mode. Print the commands as they are called.
-c Suppress linking with ld(1) and produce a .o file
for each source file. A single object file can be
named explicitly using the -o option.
-C Prevent cpp and cfront from removing comments.
-E Run only cpp on the .c files and send the result to
standard output.
-F Run only cpp and cfront on the .c files and send the
result to standard output.
-Fc Like the -F option, but the output is C source code
suitable as a .c file for cc(1).
-.suffix
Instead of using standard output for the -E , -F or -Fc
options, place the output from each .c file on a file
with the corresponding .suffix.
-k Keep the files __ctdt.c and __ctdt.o. They are used to
initialize global and static class objects. Normally
they are removed.
-NOMUNCH
-NOPATCH
Do not run munch or patch on the resulting object file.
This phase is normally needed to detect static con-
structors and destructors.
-x1 cpp debug print of files #included
-x2 cpp debug inserts #control as comments in output
-x3 cpp debug does both -x1 and -x2
+d Suppress expansion of inline functions.
+e1,+e0
These flags affect how the compiler handles tables for
virtual functions. +e1 causes the tables to be exter-
nal and initialized; +e0 causes the tables to be exter-
nal and uninitialized. If neither flag is specified
(the default), the tables are local (static) and ini-
tialized. One file with all virtuals known to it should
be compiled with +e1; the rest should be compiled with
+e0. Having one external table may significantly
reduce compile time, link time and object file size.
+i Keep C source code produced by the front end in a ..c
file. Line number information is stripped.
+V Accept regular C function declarations; use the
/usr/include directory for #include files. Support for
this option is not guaranteed in future releases
+L Generate source line number information using the for-
mat "#line %d" instead of "#%d".
+xfile
Read a file of sizes and alignments. Each line contains
three fields: a type name, the size (in bytes), and the
alignment (in bytes). This option is useful for cross
compilation.
+S Spy on cfront; that is, print some information on
stderr.
+Z30000 Set cfront lex input buffer size
+zf127 Set number of files that can be concurrently opened in cfront
-???
All other - flags are sent to the "C" compiler
/???
All /xxx flags are sent to the linker
+???
All +xxx flalgs are sent to cfront
If the environment variable INCLUDE exists, it is assumed to be a
colon separated list of directories to be searched when trying to
find '#include' files. This is an alternative to the -I flag of
cc(1).
If set, the environment variables ccpC (preprocessor), cfrontC (C++
front end), ccC (c compiler), assemblerC (assembler), linkerC
(linker), and LIBRARY (C++ library) override the defaults.
See ld(1) for loader options, as(1) for assembler options, cc(1)
for code generation options, and cpp(1) for preprocessor options.
*/
/* exit status codes
* 2 too many errors
* 1 internal error
* 0 all went well
* -1 nothing done
*/
#if defined(MSDOS) && !defined(DOS) /* Lets us work with IBM or MS compilers */
#define DOS
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#if defined(DOS)
#include <process.h>
#else
#include <sys/types.h>
#include <sys/file.h>
#endif
#include "config.h"
#define nil 0
#define EOL '\0'
typedef char *String;
typedef char **StringVec;
typedef int FileDesc;
typedef enum {false, true} boolean;
#define BADEXEC -1
#define IsChild(pid) ((pid)==0)
#define stdinDesc 0
#define stdoutDesc 1
static String PREPROCESSOR;
static String CCfrontEnd;
static String Ccompiler;
static String ASSEMBLER;
static String LINKER;
static String MUNCHER;
static String PATCHER;
static String COMPRESS;
static String MV;
static String LIB;
static String StdCClib;
static String frontEndSuffix;
static String runtimeLib;
static String cclib;
static String TMPDIR;
static String ENVPATH = "INCLUDE=";
static String DEFAULTLINKER = CC_ld;
static String INCLINK = "inclink";
static String RELINK = "relink";
#define ARGSIZE 2048
#define FILENAMESIZE 256
#define MAXARGS 128
#define MAXTMPFILES 64
#define PATHLEN 1024
#define SET true
boolean Cflag = false;
boolean Eflag = false;
boolean Fflag = false;
boolean FcFlag = false;
boolean plusIflag = false;
boolean suffixFlag = false;
boolean verboseFlag = false;
boolean fakeFlag = false;
boolean objFlag = false;
boolean ignErrFlag = false;
boolean skipAsmFlag = false;
boolean cFlag = false;
boolean noMunchFlag = false;
boolean gFlag = false;
boolean gprofFlag = false;
boolean profFlag = false;
boolean genRelocInfoFlag = false;
boolean keepctdtFlag = false;
boolean implementQuick = false;
boolean translator; /* true if generates C code */
boolean dotdotsuffix; /* true if ..c suffix */
boolean ccIsLinker; /* true if using cc for link phase */
String cppArgs[MAXARGS];
StringVec cppArgv = cppArgs;
String cppPathArgs[MAXARGS];
StringVec cppPathv = cppPathArgs;
String ccArgs[MAXARGS];
StringVec ccArgv = &ccArgs[0];
String frontEndArgs[MAXARGS];
StringVec frontEndArgv = frontEndArgs;
String linkArgs[MAXARGS]; /* Link options */
StringVec linkArgv = linkArgs;
String linkObjs[MAXARGS]; /* Objects to link */
StringVec linkObjv = linkObjs;
String linkLibs[MAXARGS]; /* Link Libraries */
StringVec linkLibv = linkLibs;
String commandv[MAXARGS];
StringVec command;
String objSpaceArgs[MAXARGS];
StringVec objSpaceArgv = &objSpaceArgs[0];
String implementArgs[MAXARGS];
StringVec implementArgv = &implementArgs[0];
char implement_count[20];
char tmpFilesList[MAXTMPFILES][FILENAMESIZE];
char xBuff[FILENAMESIZE]; /* for +x file flag */
int tmpFileCount = 0;
extern StringVec environ;
char libDirBuff[128] = CC_libdir;
static String libDir = libDirBuff;
char fileName[FILENAMESIZE]; /* Temporary */
char cppName[FILENAMESIZE]; /* Name of cpp output file */
char frontEndName[FILENAMESIZE];
char compressName[FILENAMESIZE];
char filterName[FILENAMESIZE];
char destname[FILENAMESIZE];
char objName[FILENAMESIZE];
char libPath[FILENAMESIZE];
char implementName[FILENAMESIZE]; /* Name of implement input file */
char lastLib[FILENAMESIZE]; /* last -l file file */
char ccPath[PATHLEN];
String myname, linkFile;
String suffix;
int cppDesc, dest;
int numErrors = 0;
void Error (msg1, msg2)
String msg1, msg2;
{
if (msg2 == nil || *msg2 == EOL) {
fprintf(stderr, "%s: %s\n", myname, msg1);
} else {
fprintf(stderr, "%s: %s %s\n", myname, msg1, msg2);
}
exit(1);
} /* Error */
void WarningMsg (msg1, msg2)
String msg1, msg2;
{
if (msg2 == nil || *msg2 == EOL) {
fprintf(stderr, "%s: %s\n", myname, msg1);
} else {
fprintf(stderr, "%s: %s %s\n", myname, msg1, msg2);
}
} /* WarningMsg */
int Rename (old, new)
String old;
String new;
{
if (verboseFlag) {
fprintf(stderr, "mv %s %s\n", old, new);
}
#if defined(M_XENIX)
link(old, new); /* Xenix doesn't have rename */
return unlink(old);
#else
return rename(old, new);
#endif
} /* Rename */
void Remove (file)
String file;
{
int i;
if (keepctdtFlag == false && fakeFlag == false
&& file != nil && *file != EOL) {
if (verboseFlag) {
fprintf(stderr, "rm %s\n", file);
}
unlink(file); /* Delete the file */
}
/* Remove file from temporary list */
for (i=0; i<tmpFileCount; i++)
if (strcmp(tmpFilesList[i], file) == 0) {
tmpFilesList[i][0] = EOL;
if ((i+1) == tmpFileCount) tmpFileCount--;
break;
}
} /* Remove */
void RemoveTmpFiles ()
{
int i;
for (i=0; i<tmpFileCount; i++) {
if (tmpFilesList[i][0] != EOL)
Remove(tmpFilesList[i]);
}
tmpFileCount = 0;
} /* RemoveTmpFiles */
void Quit (exitStatus)
int exitStatus;
{
RemoveTmpFiles();
exit(exitStatus);
} /* Quit */
void myclose (desc)
FileDesc desc;
{
if (fakeFlag == false && close(desc) != 0) {
fprintf(stderr, "(%d) ", desc);
perror("CCC: close failed");
}
} /* myclose */
FileDesc myopen (filename, flags, mode)
String filename;
int flags, mode;
{
int f;
if (fakeFlag == false) {
f = open(filename, flags, mode);
if (f < 0) {
fprintf(stderr, "(%s) ", filename);
perror("CCC: open failed");
Quit(1);
}
} else
f = -1;
return f;
} /* myopen */
/*
* Add an argument to the end of an argument list
*/
StringVec AddArg (l, s)
StringVec l;
String s;
{
if (s != 0 && *s != EOL) {
*l++ = s;
}
return l;
} /* AddArg */
/*
* Append a list of arguments to the end of an argument list
* Input is a space-seperated list of arguments
*/
StringVec AddArgs(l, s)
StringVec l;
String s;
{
String p = s;
for(;;) {
if (isspace(*p) || *p == EOL) {
int len = p-s;
if (len > 0) {
String r = (String) malloc(len+1);
strncpy(r, s, len);
*(r+len) = EOL;
l = AddArg(l, r);
}
if (*p == EOL) break;
while(isspace(*(p+1))) p++;
s = p+1;
}
if (*p++ == EOL) break;
}
return l;
} /* AddArgs */
/*
* Append a list of arguments to the end of an argument list
*/
StringVec AddList (v, list)
StringVec v;
StringVec list;
{
if (list == 0 || *list == EOL) {
/* fprintf(stderr, "%s: AddList: null string\n", myname); */
} else {
while (*list != 0) {
*v++ = *list++;
}
}
return v;
} /* AddList */
String newString (s)
String s;
{
String p;
p = (char*) malloc(FILENAMESIZE);
strcpy(p, s);
return p;
} /* newString */
void RegisterTmpFile (filename)
String filename;
{
int i;
if (tmpFileCount >= MAXTMPFILES) {
for (i = 0; i<MAXTMPFILES ; i++) {
unlink(tmpFilesList[i]);
tmpFilesList[i][0] = EOL;
}
tmpFileCount = 0;
}
strcpy(tmpFilesList[tmpFileCount], filename);
tmpFileCount++;
} /* RegisterTmpFile */
TmpFileName(tmpname, characteristic, type)
String tmpname;
String characteristic;
String type;
{
sprintf(tmpname, "%sC%d%s.%s", TMPDIR, getpid() % 9999, characteristic, type);
RegisterTmpFile(tmpname);
} /* TmpFileName */
FileDesc MakeTmpFile (tmpname, characteristic, type)
String tmpname;
String characteristic;
String type;
{
int t;
TmpFileName(tmpname, characteristic, type);
if (fakeFlag == false) {
t = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (t < 1) {
perror("CCC: cannot open tmp file");
exit(1);
}
} else {
t = stdoutDesc;
}
return t;
} /* MakeTmpFile */
void PrintArgList (prog, argv)
String prog;
StringVec argv;
{
int i;
fprintf(stderr, "%s ", prog);
for (i=1; argv[i] != 0; i++) {
fprintf(stderr, "%s ", argv[i]);
}
fprintf(stderr,"\n");
} /* PrintArgList */
void initexec (progname)
String progname;
{
command = commandv;
*command++ = progname;
} /* initexec */
#if !defined(DOS)
void RedirectIn (in)
FileDesc in;
{
if (in != stdinDesc) {
dup2(in, stdinDesc);
close(in);
}
} /* RedirectIn */
void RedirectOut (out)
FileDesc out;
{
if (out != stdoutDesc) {
dup2(out, stdoutDesc);
close(out);
}
} /* RedirectOut */
/* Special hack to convert vector of string pointers into a
a simple string for use in NoWaitExec.
*/
#if defined(M_XENIX)
String makecfxxargs (v)
StringVec v;
{
static char workstring[256];
strcpy(workstring, "exec ");
while (*v != 0) {
strcat(workstring,*v++);
strcat(workstring, " ");
}
return workstring;
} /* makecfxxargs */
#endif
/* Return pid of child */
int NoWaitExec (name, argv, in, out)
String name;
StringVec argv;
FileDesc in;
FileDesc out;
{
int pid;
char *path = "/bin/sh";
pid=fork();
if IsChild(pid) {
RedirectIn(in);
RedirectOut(out);
/* This hack executes cfxx from a shell
instead of via execvp. For some reason
cfxx fails if executed from execvp. Sigh.*/
#if defined(M_XENIX)
if ( name == CCfrontEnd) {
execl (path, path, "-c", makecfxxargs(argv), (char*)0 );
}
else
#endif
execvp(name, argv);
fprintf(stderr, "%s: Can not execute %s\n", myname, name);
perror("CCC: exec error");
_exit(BADEXEC);
}
return pid;
} /* NoWaitExec */
int mywait (pid)
int pid;
{
int status;
if (pid != -1) {
while ( wait(&status) != pid ) {
;
}
if (status != 0) {
if ((status & 0xff)== 0) {
status = status >> 8;
}
}
} else {
status = -1;
}
return status;
} /* mywait */
#endif
int myexec(name, argv, in, out)
String name;
String argv[];
FileDesc in;
FileDesc out;
{
int pid, status;
#if !defined(DOS)
pid = NoWaitExec(name, argv, in, out);
status = mywait(pid);
#else
status = spawnvp(P_WAIT, name, argv);
#endif
return status;
} /* myexec */
/*
* If 0 is passed as in or out, use the defaults, stdin and stdout.
*/
int execute (progfile, argv, in, out)
String progfile;
StringVec argv;
FileDesc in, out;
{
int status;
*command++ = nil; /* Terminate arg list HACK !! */
if (verboseFlag) {
PrintArgList(progfile, argv);
}
status = 0;
if (fakeFlag == false) {
status = myexec(progfile, argv, in, out);
if (status != 0) {
numErrors++;
}
if (verboseFlag && status != 0) {
fprintf(stderr,"%s: %s exited with status of %d\n",
myname, progfile, status);
}
}
return status;
} /* execute */
void NoMoreOpt (opt, arg)
char opt;
String arg;
{
if (opt != EOL) {
fprintf(stderr,
"%s: %c not understood in option %s\n", myname, opt, arg
);
Quit(1);
}
} /* NoMoreOpt */
/**************** This is case_insensitive *****************/
#define TO_UPPER(x) (islower(x) ? toupper(x) : x)
boolean is_equal (c1, c2)
char* c1;
char* c2;
{
for ( ; *c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2); c1++, c2++)
if (*c1 == EOL)
return true;
return (*c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2)) ? true : false;
} /* is_equal */
typedef enum
{INVALIDFILE, CFILE, CPLUSPLUSFILE, OBJECTFILE,
ASSEMBLERFILE, LIBRARYFILE, HEADERFILE}
FileType;
struct FileInfo {
char* suffix;
FileType type;
};
struct FileInfo fileTypeInfo[] = {
{"C", CPLUSPLUSFILE},
{"cxx", CPLUSPLUSFILE},
{"i", CFILE},
{"c", CFILE},
{"o", OBJECTFILE},
{"obj", OBJECTFILE},
{"s", ASSEMBLERFILE},
{"asm", ASSEMBLERFILE},
{"a", LIBRARYFILE},
{"lib", LIBRARYFILE},
{"h", HEADERFILE},
{"hxx", HEADERFILE},
{EOL, INVALIDFILE}
};
/*
* dir, tail, ext are VAR parameters
*/
FileType DetermineFileType (filename, dir, tail, ext)
String filename;
String *dir; /* Directory */
String *tail; /* File name (includes type) */
String *ext; /* File type (includes leading .) */
{
String p;
FileType kind;
struct FileInfo *fi;
*dir = nil; /* defaults */
*ext = nil;
*tail = fileName;
p = strlen(filename) + filename;
while (p != fileName) {
if (*p == '.' && *ext == nil) {
*ext = p;
} else if (*p == '/' || *p == '\\') {
*tail = p + 1;
*p = EOL;
*dir = fileName;
break;
}
p--;
}
/* determine kind of file it is */
if ( *ext == nil ) {
kind = LIBRARYFILE; /* Assume lib file */
} else {
for(fi = fileTypeInfo; fi->suffix != EOL; fi++)
#if defined(DOS) /* DOS filenames aren't case sensitive */
if (is_equal((*ext)+1, fi->suffix)) break;
#else
if (!strcmp((*ext)+1, fi->suffix)) break;
#endif
kind = fi->type;
}
return kind;
} /* DetermineFileType */
void SetUpHandler (sig, handler)
int sig;
void (*handler)();
{
#if defined(DOS)
int (*signalHandler)(); /* Pointer to integer function */
#else
void (*signalHandler)(); /* Pointer to integer function */
#endif
signalHandler = signal(sig, handler);
if (signalHandler == SIG_IGN) {
(void) signal(sig, SIG_IGN);
} else if ((int)signalHandler == -1) {
perror("CCC: could not set up signal handler");
}
} /* SetUpHandler */
void interupt ()
{
RemoveTmpFiles();
exit(3);
} /* interupt */
void PrintVersionAndPath ()
{
static boolean printed = false;
if (printed == false) {
printf("CCPATH = %s\n", ccPath);
printed = true; /* Only print this once */
}
} /* PrintVersionAndPath */
void HandleArgs (argc, argv)
int argc;
String *argv;
{
register int i;
for (i = 1; i < argc; i++) { /* Handle options of the form '-XXX' */
if (argv[i][0]==EOL) { /* Skip null argument */
}
else if (argv[i][0]=='-') { /* Look at args beginning with - */
switch (argv[i][1]) {
#if defined(DOS)
case 'A': /* -Ax select storage model */
NoMoreOpt(argv[i][3], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
switch (argv[i][2]) { /* Set default library */
case 'S': /* small */
#if defined(cfront2)
StdCClib = "SLcxxe";
#else
StdCClib = "SLcxx5ep";
#endif
ccArgv = AddArg(ccArgv, "-DM_I86SM");
cppArgv = AddArg(cppArgv, "-DM_I86SM");
break;
case 'M': /* medium */
#if defined(cfront2)
StdCClib = "MLcxxe";
#else
StdCClib = "MLcxx5ep";
#endif
ccArgv = AddArg(ccArgv, "-DM_I86MM");
cppArgv = AddArg(cppArgv, "-DM_I86MM");
frontEndArgv = AddArg(frontEndArgv, "+MM");
break;
case 'L': /* large */
#if defined(cfront2)
StdCClib = "Lcxxce";
#else
StdCClib = "LLcxx5ep";
#endif
ccArgv = AddArg(ccArgv, "-DM_I86LM");
cppArgv = AddArg(cppArgv, "-DM_I86LM");
frontEndArgv = AddArg(frontEndArgv, "+ML");
break;
case 'C': /* compact */
#if defined(cfront2)
StdCClib = "CLcxxe";
#else
StdCClib = "CLcxx5ep";
#endif
ccArgv = AddArg(ccArgv, "-DM_I86CM");
cppArgv = AddArg(cppArgv, "-DM_I86CM");
frontEndArgv = AddArg(frontEndArgv, "+MC");
break;
default:
NoMoreOpt(argv[i][2], argv[i]);
}
break;
case 'G': /* -Gn instruction set */
NoMoreOpt(argv[i][3], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
break;
case 'Z': /* -Zx language extensions */
NoMoreOpt(argv[i][3], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
break;
case 'g': /* -g debug mode */
NoMoreOpt(argv[i][2], argv[i]);
/* frontEndArgv = AddArg(frontEndArgv, "+L"); */
ccArgv = AddArg(ccArgv, "-Zi"); /* include debug info */
ccArgv = AddArg(ccArgv, "-Od"); /* turn off optimization */
linkArgv = AddArg(linkArgv, "/CO"); /* CodeView link */
break;
case 'w': /* -wn supress warning messages */
NoMoreOpt(argv[i][3], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
break;
#endif
case 'c': /* -c supress linking */
cFlag = SET;
NoMoreOpt(argv[i][2], argv[i]);
break;
case 'C': /* -C Keep comments */
NoMoreOpt(argv[i][2], argv[i]);
cppArgv = AddArg(cppArgv, argv[i]);
break;
case 'd': /* -d ??? (passed to cc) */
NoMoreOpt(argv[i][2], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
break;
case 'E': /* -E cpp only */
Eflag = SET;
NoMoreOpt(argv[i][2], argv[i]);
break;
case 'F': /* -F cpp & cfront only */
Fflag = SET;
if (argv[i][2] == 'c') { /* -Fc output sutable for cc */
NoMoreOpt(argv[i][3], argv[i]);
FcFlag = SET;
} else {
NoMoreOpt(argv[i][2], argv[i]);
} /* if */
break;
case 'i': /* added this */
ignErrFlag = SET;
break;
case 'k': /* keep __ctdt.c and __ctdt.o */
keepctdtFlag = SET;
break;
case 'l': /* -lfile link with library file */
strcpy(lastLib, argv[i]+2);
#if defined(DOS)
linkLibv = AddArg(linkLibv, argv[i]+2);
#else
linkLibv = AddArg(linkLibv, argv[i]);
#endif
break;
#if defined(M_XENIX)
case 'L': /* -L in Xenix handled special */
strcpy(libPath, argv[i]+2);
break;
#endif
case 'N': /* -NOMUNCH -NOPATCH */
/* don't munch/patch result */
if (strcmp(argv[i],"-NOMUNCH")==0) {
noMunchFlag = SET;
} else {
ccArgv = AddArg(ccArgv, argv[i]);
}
break;
case 'n': /* print, but don't do it */
NoMoreOpt(argv[i][2], argv[i]);
verboseFlag = SET;
fakeFlag = SET;
PrintVersionAndPath();
break;
case 'o': /* -ofile name of output file */
if (argv[i][2] != '\0')
strcpy(objName, argv[i]+2);
else
strcpy(objName, argv[++i]);
if (*objName == EOL) {
WarningMsg(
"No object specified after -o, using a.out", nil);
} else {
objFlag = SET;
#if !defined(DOS)
linkArgv = AddArg(linkArgv, "-o");
linkArgv = AddArg(linkArgv, objName);
#endif
}
break;
case 'p':
if (argv[i][2] == 'g') { /* -pg gprof*/
NoMoreOpt(argv[i][3], argv[i]);
gprofFlag = SET;
profFlag = false;
} else { /* -p prof */
NoMoreOpt(argv[i][2], argv[i]);
profFlag = SET;
gprofFlag = false;
}
ccArgv = AddArg(ccArgv, argv[i]);
break;
case 'r': /* -r ??? (passed to cc) */
genRelocInfoFlag = SET;
NoMoreOpt(argv[i][2], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
break;
case 'S': /* -S produce assembly source */
skipAsmFlag = SET;
NoMoreOpt(argv[i][2], argv[i]);
ccArgv = AddArg(ccArgv, argv[i]);
break;
case 'v': /* -v verbose */
verboseFlag = SET;
NoMoreOpt(argv[i][2], argv[i]);
/* PrintVersionAndPath(); */
break;
case 'I': /* -Ifile include directory */
cppArgv = AddArg(cppArgv, argv[i]);
break;
case 'x': /* -xn cpp debug mode */
case 'D': /* -Dsym define cpp symbol */
case 'U': /* -Usym undefine cpp symbol */
cppArgv = AddArg(cppArgv, argv[i]);
break;
case '.': /* -.suffix suffix for output */
if (suffixFlag) {
Error("Not allowed to specify more than one suffix",
nil);
} /* if */
suffixFlag = SET;
suffix = &argv[i][1];
break;
case 'X': /* -X"class<parms>" - implement */
Implement(argv[i]+2);
break;
case 'Q': /* -Q - implement quick */
NoMoreOpt(argv[i][2], argv[i]);
implementQuick = true;
break;
default: /* Otherwise, send it to cc */
ccArgv = AddArg(ccArgv, argv[i]);
break;
} /* switch (argv[i][1]) */
} else if (argv[i][0] == '/') { /* /foo options go to the linker */
linkArgv = AddArg(linkArgv, argv[i]);
} else if (argv[i][0] == '+') {
/* handle options of the form '+XXX' */
switch (argv[i][1]) {
case 'd': /* +d Don't expand inlines */
frontEndArgv = AddArg(frontEndArgv, argv[i]);
break;
case 'e': /* +e1 +e0 C++ vtbl generation */
frontEndArgv = AddArg(frontEndArgv, argv[i]);
break;
case 'V': /* +V Accept K&R C function decl */
NoMoreOpt(argv[i][2], argv[i]);
strcpy(libDir, " -I/usr/include");
break;
case 'L': /* +L Use #line instead of # */
NoMoreOpt(argv[i][2], argv[i]);
break;
case 'x': /* +xfile Alignment file */
if (argv[i][2] != '\0') {
frontEndArgv = AddArg(frontEndArgv, argv[i]);
} else {
i++;
if (argv[i] == EOL) {
Error("No arg specified after +x", nil);
} else {
strcpy(xBuff, "+x");
strcat(xBuff, argv[i]);
frontEndArgv = AddArg(frontEndArgv, xBuff);
}
}
break;
case 'S': /* +S spy on cfront */
NoMoreOpt(argv[i][2], argv[i]);
frontEndArgv = AddArg(frontEndArgv, argv[i]);
break;
case 'i': /* +i keep cc source in ..c */
plusIflag = SET;
break;
case 'z': /* +zxxx cfront size options */
frontEndArgv = AddArg(frontEndArgv, argv[i]);
break;
default: /* otherwise send it to cfront */
frontEndArgv = AddArg(frontEndArgv, argv[i]);
break;
}
} else {
if (processFile(argv[i]) != 0) {
Quit(1);
}
}
}
} /* HandleArgs */
String SetDefaultFromEnv();
void GetCCPath();
void Init (envp)
StringVec envp;
{
#if defined(DOS) || defined(MSDOS)
PREPROCESSOR = SetDefaultFromEnv(envp, "CCPC=", CC_cpp);
CCfrontEnd = SetDefaultFromEnv(envp, "CFRONTC=", CC_compiler);
frontEndSuffix = SetDefaultFromEnv(envp, "SUFFIXC=", CC_suffix);
StdCClib = SetDefaultFromEnv(envp, "LIBRARY=", CC_library);
runtimeLib = SetDefaultFromEnv(envp, "RUNTIMELIBC", CC_rt);
translator = (boolean)(strcmp(frontEndSuffix, ".s") != 0);
dotdotsuffix = (boolean)(strcmp(frontEndSuffix, "..c") == 0);
Ccompiler = SetDefaultFromEnv(envp, "CC=", CC_cc);
ASSEMBLER = SetDefaultFromEnv(envp, "ASSEMBLERC=", CC_as);
LINKER = SetDefaultFromEnv(envp, "LINKERC=", DEFAULTLINKER);
MUNCHER = SetDefaultFromEnv(envp, "MUNCHC=", CC_munch);
PATCHER = SetDefaultFromEnv(envp, "PATCHC=", CC_patch);
LIB = SetDefaultFromEnv(envp, "LIBC=", CC_lib);
TMPDIR = SetDefaultFromEnv(envp, "TMP=", CC_tmp);
COMPRESS = SetDefaultFromEnv(envp, "COMPRESS=", CC_compress);
MV = SetDefaultFromEnv(envp, "MV=", CC_mv);
#else
PREPROCESSOR = SetDefaultFromEnv(envp, "ccpC=", CC_cpp);
CCfrontEnd = SetDefaultFromEnv(envp, "cfrontC=", CC_compiler);
frontEndSuffix = SetDefaultFromEnv(envp, "suffixC=", CC_suffix);
StdCClib = SetDefaultFromEnv(envp, "LIBRARY=", CC_library);
runtimeLib = SetDefaultFromEnv(envp, "runTimeLibC", CC_rt);
translator = (boolean)(strcmp(frontEndSuffix, ".s") != 0);
dotdotsuffix = (boolean)(strcmp(frontEndSuffix, "..c") == 0);
Ccompiler = SetDefaultFromEnv(envp, "ccC=", CC_cc);
ASSEMBLER = SetDefaultFromEnv(envp, "assemblerC=", CC_as);
LINKER = SetDefaultFromEnv(envp, "linkerC=", DEFAULTLINKER);
MUNCHER = SetDefaultFromEnv(envp, "munchC=", CC_munch);
PATCHER = SetDefaultFromEnv(envp, "patchC=", CC_patch);
LIB = SetDefaultFromEnv(envp, "libC=", CC_lib);
TMPDIR = SetDefaultFromEnv(envp, "TMP=", CC_tmp);
COMPRESS = SetDefaultFromEnv(envp, "COMPRESS=", CC_compress);
#endif
cclib = "-lc";
GetCCPath(environ);
ccArgv = AddArgs(ccArgv, CCARGS);
frontEndArgv = AddArg(frontEndArgv, CCFRONTARGS);
implement_count[0] = '\0';
} /* Init */
int main (argc, argv, envp)
int argc;
StringVec argv, envp;
{
myname = argv[0];
if (argc <= 1) {
fprintf(stderr,"usage: %s [options] [ file.{c,o,s} ] \n", myname);
exit(-1);
}
SetUpHandler(SIGINT, interupt);
#if defined(DOS)
SetUpHandler(SIGTERM, interupt);
SetUpHandler(SIGBREAK, interupt);
#else
SetUpHandler(SIGQUIT, interupt);
SetUpHandler(SIGHUP, interupt);
#endif
Init(envp);
HandleArgs(argc, argv);
if (objFlag == false) {
strcpy(objName, "a.out");
}
if (numErrors != 0) {
Quit(2);
}
if (Eflag || Fflag || FcFlag || skipAsmFlag) {
Quit(0);
}
if (cFlag) {
Quit(0);
}
Quit(LinkPhase());
} /* main */
#define INCLUDEFLAG "-I"
#define INCLUDEFLAGLEN 2
#if defined(DOS)
#define INCLUDE_SEPERATOR ';'
#else
#define INCLUDE_SEPERATOR ':'
#endif
void AddIncludes (line)
String line;
{
String a, b, t;
boolean done;
if (line == nil) {
return;
}
a = &line[0];
b = a;
done = false;
while (done == false) {
done = (boolean) (*b == EOL || *b == '\n' || (b-&line[0]) >= ARGSIZE);
if (*b == INCLUDE_SEPERATOR || *b == '\n' || *b == EOL) {
if (b>a) {
*b = EOL;
t = (char *) malloc(b-a + 1 + INCLUDEFLAGLEN); /* +1=EOL +2=-I */
strcpy(t, INCLUDEFLAG);
strcat(t, a);
cppPathv = AddArg(cppPathv, t);
*b = INCLUDE_SEPERATOR; /* restore so can print ccPath */
}
a = b+1;
}
b++;
}
} /* AddIncludes */
String ReadEnv (env, pathVar)
StringVec env;
String pathVar;
{
int i, len;
len = strlen(pathVar);
for (i = 0; env[i] != nil; i++) {
if (strncmp(env[i], pathVar, len) == 0) {
return &env[i][len];
}
}
return nil;
} /* ReadEnv */
String SetDefaultFromEnv (envp, envName, defaultVal)
StringVec envp;
String envName;
String defaultVal;
{
String tmp;
tmp = ReadEnv(envp, envName);
if (tmp == nil) {
tmp = defaultVal;
}
return tmp;
} /* SetDefaultFromEnv */
void GetCCPath (env)
StringVec env;
{
String tmp;
tmp = ReadEnv(env, ENVPATH);
if (tmp != nil) {
strcpy(ccPath, tmp);
AddIncludes(ccPath);
}
} /* GetCCPath */
int Move (filename, oldsuffix, newsuffix)
String filename, oldsuffix, newsuffix;
{
char aBuffer[FILENAMESIZE], aBuffer2[FILENAMESIZE];
strcpy(aBuffer, filename);
strcat(aBuffer, oldsuffix);
strcpy(aBuffer2, filename);
strcat(aBuffer2, newsuffix);
return Rename(aBuffer, aBuffer2);
} /* Move */
/*
* process a given file.
* either cc, as or just link it.
*/
int processFile (fullPathName)
String fullPathName;
{
String dir; /* Directory */
String fileTail; /* File name (includes type) */
String ext; /* File type (includes leading .) */
FileType fileType;
int status;
linkFile = nil;
strcpy(fileName, fullPathName);
fileType = DetermineFileType(fileName, &dir, &fileTail, &ext);
/*
* set linkFile name
*/
if (fileType == CPLUSPLUSFILE ||
fileType == ASSEMBLERFILE ||
fileType == CFILE) {
strcpy(ext, OBJ_Suffix); /* change xxx.c to xxx.o */
linkFile = newString(fileTail);
/* Set up to delete the object file if it will be linked. */
if (fileType == CPLUSPLUSFILE && cFlag == false) {
RegisterTmpFile(linkFile);
}
} else if (fileType == OBJECTFILE) {
linkFile = newString(fullPathName);
} else if (fileType == LIBRARYFILE ||
fileType == CFILE ||
fileType == INVALIDFILE) {
linkFile = newString(fullPathName);
} else if (fileType == HEADERFILE) {
implementArgv = AddArg(implementArgv, fullPathName);
}
if (ext != nil) {
*ext = EOL; /* truncate so fileTail has no ext */
}
/*
* set front end name
*/
if (Fflag) {
if (suffixFlag) {
strcpy(frontEndName, fileTail);
strcat(frontEndName, suffix);
} else {
*frontEndName = EOL;
}
} else {
strcpy(frontEndName, fileTail);
strcat(frontEndName, frontEndSuffix);
}
/*
* preprocess, cfront, compile
*/
switch (fileType) {
case LIBRARYFILE:
#if defined(DOS)
linkLibv = AddArg(linkLibv, fullPathName);
break;
#endif
case OBJECTFILE:
case INVALIDFILE:
linkObjv = AddArg(linkObjv, linkFile);
return 0;
case CPLUSPLUSFILE:
case CFILE:
linkObjv = AddArg(linkObjv, linkFile);
status = CPPphase(fullPathName, fileTail); /* Preprocess */
if (Eflag || status != 0) {
return status;
}
return compilePhase(fullPathName, fileTail, fileType); /* Compile */
case ASSEMBLERFILE:
if (skipAsmFlag == false) {
return asmPhase(fullPathName, fileTail); /* Assemble */
}
}
return 0;
} /* processFile */
compilePhase (fullPathName, tail, fileType)
String fullPathName; /* fullPathname to preprocess */
String tail; /* file name in fullPathName */
FileType fileType; /* type of original source */
{
int status;
/* translate (cfront) */
if (fileType == CPLUSPLUSFILE) {
status = FrontEndPhase(fullPathName, frontEndName, cppName);
/*
#if defined(DOS) || defined(M_XENIX)
TmpFileName(compressName, "cmp", "i");
status = FrontEndPhase(fullPathName, compressName, cppName);
#else
status = FrontEndPhase(fullPathName, frontEndName, cppName);
#endif
*/
if (status != 0) {
if (plusIflag == false && fileType == CPLUSPLUSFILE) {
Remove(frontEndName);
/*
#if defined(DOS) || defined(M_XENIX)
Remove(compressName);
#else
Remove(frontEndName);
#endif
*/
}
#if defined(sparc)
/* cfront21 on unix creates a .c instead of a ..c file */
if (plusIflag && !dotdotsuffix && fileType == CPLUSPLUSFILE)
Move(tail, ".c", "..c");
#endif
return status;
}
Remove(cppName);
/* Compress output */
/*
#if defined(DOS) || defined(M_XENIX)
status = CompressPhase(frontEndName, compressName);
if (status != 0) {
return status;
}
Remove(compressName);
#endif
*/
/* Filter output */
if (plusIflag && (Fflag == false || suffixFlag)) {
status = FilterPhase(frontEndName, tail);
if (status != 0) {
return status;
}
}
if (Fflag) {
return status;
}
} /* End frontEnd processing */
status = ccPhase(tail, fileType); /* compile (cc) */
if (plusIflag == false && fileType == CPLUSPLUSFILE) {
Remove(frontEndName);
}
if (plusIflag && !dotdotsuffix && fileType == CPLUSPLUSFILE)
Move(tail, ".c", "..c");
if (status != 0) {
return status;
}
#if defined(DOS)
if (translator) {
return constPhase(); /* constructor (DOS ONLY) */
}
#endif
if (dotdotsuffix) {
if (skipAsmFlag) {
return Move(tail, "..s", ".s");
} else {
return Move(tail, "..o", OBJ_Suffix);
}
}
return status;
} /* compilePhase */
/*
* The following tranformations are done by '/bin/cc'.
* We have to do them ourselves.
*
* '-g' ==> '-lg' at end of args
* '-pg' ==> '/lib/gcrt0.o'
* '-p' ==> '/lib/mcrt0.o'
*/
int TransformCCArgs () {
register int i, j = 0;
boolean copy;
for (i = 0; i < MAXARGS; i++) {
if (ccArgs[i] == 0) {
break;
}
copy = true;
if (ccArgs[i][0] == '-') {
switch (ccArgs[i][1]) {
case 'g':
gFlag = true;
copy = false;
break;
case 'p':
if (ccArgs[i][2] == 'g') {
runtimeLib = "/lib/gcrt0.o";
} else {
runtimeLib = "/lib/mcrt0.o";
}
copy = false;
break;
}
}
if (copy) {
ccArgs[j++] = ccArgs[i];
}
}
ccArgs[j++] = runtimeLib;
while (j < MAXARGS && ccArgs[j] != 0) {
ccArgs[j++] = 0;
}
} /* TransformCCArgs */
int CPPphase (fullPathName, tail)
String fullPathName; /* fullPathname to preprocess */
String tail; /* file name in fullPathName */
{
int status;
initexec(PREPROCESSOR);
command = AddList(command, cppArgs);
#if defined(cfront2) || defined(cfront21)
command = AddArg(command, "-D__cplusplus=1"); /* for Ansi compatibility */
#endif
command = AddArg(command, "-Dc_plusplus=1");
command = AddArg(command, implement_count);
command = AddArgs(command, CPPARGS);
command = AddList(command, cppPathArgs);
if (translator) {
command = AddArg(command, libDir);
}
command = AddArg(command, fullPathName); /* Input file name */
if (Eflag) {
if (suffixFlag) {
strcpy(destname, tail);
strcat(destname, suffix);
command = AddArg(command, destname); /* output file name */
}
status = execute(PREPROCESSOR, commandv, stdinDesc, stdoutDesc);
} else {
TmpFileName(cppName, "cpp", "C");
command = AddArg(command, cppName); /* output file name */
status = execute(PREPROCESSOR, commandv, stdinDesc, stdoutDesc);
}
return status;
} /* CPPphase */
int FrontEndPhase (fullPathName, out, in)
String fullPathName;
String out;
String in;
{
int status;
char aBuffer[FILENAMESIZE];
if (verboseFlag == false) {
fprintf(stderr, "C++ Compile: %s\n", fullPathName);
}
initexec(CCfrontEnd);
command = AddList(command, frontEndArgs);
#if defined(DOS) || defined(M_XENIX)
strcpy(aBuffer, "+f");
strcat(aBuffer, fullPathName);
command = AddArg(command, strdup(aBuffer));
strcpy(aBuffer, "+i");
strcat(aBuffer, in);
command = AddArg(command, strdup(aBuffer));
if (*out != EOL) {
strcpy(aBuffer, "+o");
strcat(aBuffer, out);
command = AddArg(command, strdup(aBuffer));
}
status = execute(CCfrontEnd, commandv, stdinDesc, stdoutDesc);
if (status == 217) {
status = 0; /* ******** HACK ALERT ********** */
numErrors--;
}
#else
cppDesc = myopen(in, O_RDONLY, 0644);
if (translator) { /* cfront */
command = AddArg(command, "+L");
strcpy(aBuffer, "+f");
strcat(aBuffer, fullPathName);
command = AddArg(command, strdup(aBuffer));
} else { /* g++ */
command = AddArg(command, "-quiet");
}
if (Fflag) {
if (suffixFlag) {
dest = myopen(out, O_WRONLY | O_CREAT | O_TRUNC, 0644);
status = execute(CCfrontEnd, commandv, cppDesc, dest);
myclose(dest);
} else {
dest = stdoutDesc;
status = execute(CCfrontEnd, commandv, cppDesc, dest);
}
} else {
int frontEndDesc;
frontEndDesc = myopen(out, O_WRONLY | O_CREAT | O_TRUNC, 0644);
status = execute(CCfrontEnd, commandv, cppDesc, frontEndDesc);
myclose(frontEndDesc);
}
myclose(cppDesc);
#endif
return status;
} /* FrontEndPhase */
int CompressPhase (out, in)
String out;
String in;
{
int status;
initexec(COMPRESS);
command = AddArg(command, in);
command = AddArg(command, out);
status = execute(COMPRESS, commandv, stdinDesc, stdoutDesc);
if (status != 0) {
WarningMsg(COMPRESS, "error");
}
return status;
} /* CompressPhase */
/*
* Filter out #line directives
*/
int FilterPhase (fullPathName, fileTail)
String fullPathName;
String fileTail;
{
#define BUFSIZE 1028
int status;
if (plusIflag) {
register char prev = '\n';
char buffer[BUFSIZE];
int inDesc;
int filterDesc;
boolean skip_newline = false;
strcpy(filterName, fileTail);
strcat(filterName, ".f");
filterDesc = myopen(filterName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
inDesc = myopen(fullPathName, O_RDONLY, 0644);
if (verboseFlag) {
fprintf(stderr, "filter %s %s\n", fullPathName, filterName);
}
if (fakeFlag == false)
for (;;) {
register char* in = buffer;
register char* out = buffer;
register char* end = in + read(inDesc, in, BUFSIZE);
if (end == in) break; /* stop at end of file */
if (skip_newline) { /* if skipping at end of prev buf */
while (in < end && *in != '\n') in++; /* Skip to new line */
prev = *in;
skip_newline = false;
}
while (in < end) { /* search for \n# */
if (prev != '\n' || *in != '#')
*out++ = prev = *in++;
else {
while (in < end && *in != '\n') in++; /* Skip to new line */
if (in < end)
prev = *in++;
else
skip_newline = true;
}
}
if (out > buffer) /* Write buffer */
write(filterDesc, buffer, out - buffer);
}
myclose(inDesc);
myclose(filterDesc);
Remove(frontEndName); /* required by DOS rename command */
status = Rename(filterName, frontEndName);
if (status != 0) {
perror("CCC: error in filter phase");
}
}
return status;
} /* FilterPhase */
int ccPhase (tail, fileType)
String tail;
FileType fileType; /* type of original source file */
{
int status;
char aBuffer[FILENAMESIZE];
char bBuffer[FILENAMESIZE];
initexec(Ccompiler);
command = AddList(command, ccArgs);
command = AddArg(command, "-c");
#if defined(DOS)
command = AddArg(command, "-NM");
command = AddArg(command, tail);
strcpy(bBuffer, "-Fo");
strcat(bBuffer, linkFile);
command = AddArg(command, bBuffer);
strcpy(aBuffer, "-Tc");
strcat(aBuffer, frontEndName);
command = AddArg(command, aBuffer);
#else
if (objFlag && cFlag) {
command = AddArg(command, "-o");
command = AddArg(command, objName);
}
/* Allow C files to skip front end */
if (fileType == CFILE)
command = AddArg(command, cppName);
else
command = AddArg(command, frontEndName);
#endif
status = execute(Ccompiler, commandv, stdinDesc, stdoutDesc);
if (status != 0) {
Remove(linkFile);
}
return status;
} /* ccPhase */
#if defined(DOS) || defined(M_XENIX)
/*
* Implement constructors and destructors for an object file
*/
int constPhase ()
{
int status;
initexec("mxx");
#if defined(DOS)
command = AddArg(command, "-4");
#endif
command = AddArg(command, linkFile);
status = execute("mxx", commandv, stdinDesc, stdoutDesc);
return status;
} /* constPhase */
#endif
int asmPhase (fullPathName, tail)
String fullPathName, tail;
{
char aBuffer[FILENAMESIZE];
initexec(ASSEMBLER);
command = AddArg(command, "-o");
strcpy(aBuffer, tail);
strcat(aBuffer, ".o"); /* out from cc -S */
command = AddArg(command, aBuffer);
command = AddArg(command, fullPathName);
return execute(ASSEMBLER, commandv, stdinDesc, stdoutDesc);
} /* asmPhase */
int RecompileWithMunchPhase ()
{
int status;
initexec(Ccompiler);
command = AddArg(command, "-c");
command = AddArg(command, "__ctdt.c");
if (keepctdtFlag == false) {
RegisterTmpFile("__ctdt.o");
}
(void) execute(Ccompiler, commandv, stdinDesc, stdoutDesc);
initexec(LINKER);
command = AddList(command, ccArgs);
command = AddArg(command, "__ctdt.o");
command = AddList(command, linkObjs);
command = AddList(command, linkArgs);
command = AddArg(command, StdCClib);
status = execute(LINKER, commandv, stdinDesc, stdoutDesc);
return status;
} /* RecompileWithMunchPhase */
int LinkPhase () {
int status;
#if defined(DOS)
status = dosLink(DEFAULTLINKER);
#else
if (strcmp(LINKER, INCLINK) == 0) {
ccIsLinker = false;
status = Inclink();
} else {
ccIsLinker = true;
status = DefaultLink();
}
#endif
return status;
} /* LinkPhase */
int Inclink () {
TransformCCArgs();
return PassOne(RELINK);
} /* Inclink */
int DefaultLink () {
int status;
if (runtimeLib[0] != '\0') {
ccIsLinker = false;
TransformCCArgs();
linkArgv = AddArg(linkArgv, "-C");
}
status = PassOne(LINKER);
if (translator) { /* cfront translator */
if (status != 0) {
return status;
}
status = PassTwo();
}
return status;
} /* DefaultLink */
#if defined(DOS)
int dosLink (linker)
char* linker;
{
int status;
/*
* format is:
* LINK objects , runfile , listfile , librarylist , options ;
*/
initexec(linker); /* LINK */
command = AddList(command, linkObjs); /* objects */
command = AddArg(command, ",");
if (objFlag) { /* runfile */
command = AddArg(command, objName);
}
command = AddArg(command, "/NOIGNORECASE");
command = AddArg(command, ",");
/* listfile */
command = AddArg(command, ",");
command = AddList(command, linkLibs); /* librarylist */
command = AddArgs(command, StdCClib);
command = AddList(command, linkArgs);
command = AddArg(command, ";");
status = execute(linker, commandv, stdinDesc, stdoutDesc);
return status;
} /* dosLink */
#endif
int PassOne (linker)
char* linker;
{
int status;
initexec(linker);
command = AddList(command, ccArgs);
command = AddList(command, linkObjs);
command = AddList(command, linkLibs);
#if defined(InterViews) /* what is this for??? */
if (keepctdtFlag)
command = AddArg(command, "-k");
#endif
command = AddList(command, linkArgs);
command = AddArg(command, StdCClib);
if (ccIsLinker == false) {
if (gFlag) {
command = AddArg(command, "-lg");
}
command = AddArg(command, cclib);
if (linker == RELINK) {
command = AddList(command, objSpaceArgs);
}
}
status = execute(linker, commandv, stdinDesc, stdoutDesc);
return status;
} /* PassOne */
int PassTwo () {
int status;
#if defined(CC_domunch)
status = MunchPhase();
#else
status = PatchPhase();
#endif
return status;
} /* PassTwo */
int PatchPhase () {
int status;
if (noMunchFlag == false) {
initexec(PATCHER);
command = AddArg(command, objName);
status = execute(PATCHER, commandv, stdinDesc, stdoutDesc);
}
return status;
} /* PatchPhase */
int MunchPhase () {
int status;
int nmDesc, munchDesc;
char nmName[FILENAMESIZE];
if (genRelocInfoFlag == false && noMunchFlag == false) {
#if !defined(M_XENIX)
nmDesc = MakeTmpFile(nmName, "nm", "txt");
initexec("nm");
command = AddArg(command, objName);
status = execute("/bin/nm", commandv, stdinDesc, nmDesc);
if (status != 0) {
return status;
}
close(nmDesc);
close(stdoutDesc);
/* input */
nmDesc = myopen(nmName, O_RDONLY, 0644);
/* output */
munchDesc = myopen("__ctdt.c", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (keepctdtFlag == false) {
RegisterTmpFile("__ctdt.c");
}
#endif
initexec(MUNCHER);
if (profFlag) {
command = AddArg(command, "-p");
} else if (gprofFlag) {
command = AddArg(command, "-pg");
}
#if defined(M_XENIX)
command = AddArg(command, objName);
#endif
status = execute(MUNCHER, commandv, nmDesc, munchDesc);
#if !defined(M_XENIX)
if (status != 0) {
status = RecompileWithMunchPhase();
if (status != 0) {
return status;
}
}
#endif
}
return 0;
} /* MunchPhase */
libPhase(fileName)
String fileName;
{
char cmd[100];
int status;
initexec(LIB);
#if defined(DOS)
sprintf(cmd, "%s -+%s;", lastLib, fileName);
command = AddArg(command, cmd);
#else
command = AddArg(command, "rl");
command = AddArg(command, lastLib);
command = AddArg(command, fileName);
#endif
status = execute(LIB, commandv, stdinDesc, stdoutDesc);
return status;
} /* libPhase */
Implement(what)
String what;
{
int status;
int i;
StringVec argv = implementArgs;
FILE* implementfile;
if (*what == EOL)
Error ("You must specify \"class<parms>\" to implement with the -X option",
NULL);
if (*objName == EOL)
Error ("When using -X, you must specify an object name with the -o option",
NULL);
if (*lastLib == EOL)
Error ("When using -X, you must specify a library name with the -l option",
NULL);
objFlag = false;
TmpFileName(implementName, "imp", "C");
implementfile = fopen(implementName, "w");
fprintf(implementfile, "// CCC implementation input file\n");
for (i=0; argv[i] != 0; i++)
fprintf(implementfile, "#include <%s>\n", argv[i]);
Eflag = false; /* Disable the -E option */
cFlag = SET; /* Don't try to link */
/*
* Check for the fast track - a single compile
*/
if (implementQuick) {
char* what_name = strdup(what);
char* p = strchr(what_name, '<');
sprintf(frontEndName, "%s%s", objName, frontEndSuffix);
if (p != NULL) *p = '\0'; /* Get the name of the class to implement */
fprintf(implementfile,
"#pragma defmacro IMPLEMENT_1 implement delimiter=> lines %s\n",
what_name);
fprintf(implementfile, "IMPLEMENT_1 %s\n", what);
fclose(implementfile);
linkFile = newString(objName);
strcat(linkFile, OBJ_Suffix);
/* Preprocess */
status = CPPphase(implementName, objName);
if (status != 0) return status;
status = compilePhase(implementName, objName, CPLUSPLUSFILE);
Remove(implementName);
libPhase(linkFile);
Remove(linkFile);
} else {
int count;
fprintf(implementfile,
"#pragma defmacro IMPLEMENT_N implement_n delimiter=> lines\n");
fprintf(implementfile,
"#pragma defmacro DECLARE_ONCE declare_once delimiter=> recursive lines\n");
fprintf(implementfile, "DECLARE_ONCE %s\n", what);
fprintf(implementfile, "MACRO EXPANDING EXPAND_IMPLEMENT(count)\n");
fprintf(implementfile, "{IMPLEMENT_N count %s}\n", what);
fprintf(implementfile, "EXPAND_IMPLEMENT(Count)\n");
fclose(implementfile);
linkFile = newString(objName);
if (strlen(objName) > 7) objName[7] = '\0';
for(count=0;;count++) {
char newImpName[FILENAMESIZE];
char moduleName[FILENAMESIZE];
if (strlen(objName) > 6 && count > 9) objName[6] = '\0';
sprintf(frontEndName, "%s%d%s", objName, count, frontEndSuffix);
sprintf(linkFile, "%s%d%s", objName, count, OBJ_Suffix);
sprintf(moduleName, "%s%d", objName, count);
sprintf(newImpName, "%s%s.%s", TMPDIR, moduleName, "C");
sprintf(implement_count, "-DCount=%d", count);
Rename(implementName,newImpName);
status = CPPphase(newImpName, objName);
if (status != 0) break;
status = compilePhase(newImpName, moduleName, CPLUSPLUSFILE);
libPhase(linkFile);
Remove(linkFile);
strcpy(implementName,newImpName);
}
if (count > 0) {
numErrors--; /* We expect 1 error from cpp */
status = 0;
}
Remove(implementName);
}
return status;
} /* Implement */